package cn.ilikes.tools.nosql.jpa.clients;

import org.apache.hadoop.hbase.client.Result;
import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.JPASQLPersistenUnitEnv;
import cn.ilikes.tools.nosql.jpa.classloads.porxys.LazyInitializerFactory;
import cn.ilikes.tools.nosql.jpa.clients.handers.AbDataHander;
import cn.ilikes.tools.nosql.jpa.clients.handers.hbases.HBaseUtils;
import cn.ilikes.tools.nosql.jpa.clients.indexs.ABClientIndex;
import cn.ilikes.tools.nosql.jpa.graphs.Node;
import cn.ilikes.tools.nosql.jpa.graphs.NodeLifeCycle.LifeCycle;
import cn.ilikes.tools.nosql.jpa.metadatas.EntityMetaData;
import cn.ilikes.tools.nosql.jpa.persistences.contexts.AbstractContext;

public abstract class AbClient extends ClientBaseImple implements Client {

	private Logger logger = Loggerfactory.instance(AbClient.class);

	private AbDataHander dataHander;

	private ABClientIndex clientIndex;

	private AbstractContext abstractContext;

	public AbClient(AbDataHander dataHander, ABClientIndex clientIndex, JPASQLPersistenUnitEnv persistenUnitEnv) {
		super(persistenUnitEnv);
		this.dataHander = dataHander;
		this.clientIndex = clientIndex;
	}

	public void setAbstractContext(AbstractContext abstractContext) {
		this.abstractContext = abstractContext;
	}

	public AbDataHander getDataHander() {
		return dataHander;
	}

	public ABClientIndex getClientIndex() {
		return clientIndex;
	}

	@Override
	public boolean isOpen() {
		return (dataHander.isOpen() && clientIndex.isOpen());
	}

	public void init() {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "Ab Client ");
		dataHander.init();
//		clientIndex.init();
	}

	@Override
	public Node save(Node node) throws JPASQLClientsException {

		dataHander.save(node);
		clientIndex.create(node);
		return node;
	}

	private byte[] findIndex(EntityMetaData entityMetaData, Object key) throws JPASQLClientsException {
		if (clientIndex.exist(entityMetaData, key)) {
			Result result = dataHander.findId(entityMetaData, key);
			return result.getRow();
		} else {
			Result result = dataHander.findId(entityMetaData, key);
			return result.getRow();
		}
	}

	public Node load(EntityMetaData entityMetaData, Object key) throws JPASQLClientsException {
		LazyInitializerFactory lazyInitializerFactory = abstractContext.getPersistenUnitEnv().getSystemEnv().getLazyInitializerFactory();
		byte[] keyId = findIndex(entityMetaData, key);
		if (keyId == null)
			throw new JPASQLClientsException("not load key : " + key + "    Entity Meta Data  ! ");
		Object keyId_ = HBaseUtils.getByteTosObject(keyId, entityMetaData.getEntityId().getField());
		Object proxy = lazyInitializerFactory.getProxy(entityMetaData, keyId_, this.getAbstractContext());
		Node node = Node.createtNode(entityMetaData, proxy, LifeCycle.managed);
		return node;

	}

	public Node findById(EntityMetaData entityMetaData, Object key) throws JPASQLClientsException

	{
		if(!clientIndex.exist(entityMetaData, key))return null;
		Result result = dataHander.find(entityMetaData, key);
		Node node = switchNode(entityMetaData, result);
		return node;

	}

	public AbstractContext getAbstractContext() {
		return abstractContext;
	}

	@Override
	public Long selectSizeByKeyId(Object keyId, EntityMetaData entityMetaData) throws JPASQLClientsException {

		return clientIndex.selectSizeByKeyId(keyId, entityMetaData);
	}

	public abstract Node switchNode(EntityMetaData entityMetaData, Result result) throws JPASQLClientsException;

	@Override
	public void flush() {
		dataHander.flush();
		clientIndex.flush();

	}

	@Override
	public void commit() {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, "AbClient  commit");
		AbDataHander dataHander = this.dataHander;
		dataHander.flush();
		ABClientIndex clientIndex = this.clientIndex;
		clientIndex.flush();

	}

	@Override
	public void rollback() {
		AbDataHander dataHander = this.dataHander;
		dataHander.rollback();
		ABClientIndex clientIndex = this.clientIndex;
		clientIndex.rollback();
	}

	@Override
	public Object findValue(EntityMetaData targetEntityMetaData, Object keyId, Class<?> valueClaz, String getfamily, String qualifier) throws JPASQLClientsException {

		AbDataHander dataHander = getDataHander();
		byte[] result = dataHander.findValue(targetEntityMetaData, keyId, getfamily, qualifier);
		return HBaseUtils.getByteTosObject(result, valueClaz);

	}

	@Override
	public void delete(Node node) throws JPASQLClientsException {
		AbDataHander dataHander = this.dataHander;
		dataHander.remove(node);
		ABClientIndex clientIndex = this.clientIndex;
		clientIndex.remove(node);
	}

}